import Manager from 'cloudstudio-sdk/Manager'
import * as React from 'react'
import { editor, file, actions, PluginContext, appRegistry, IDisposable } from 'cloudstudio-extension'

import * as minimatch from 'minimatch'

import { parse } from './Parser'

const context = new PluginContext({})

// 插件唯一 key
// 一定要确保代码中 pluginKey 的唯一性，推荐使用「开发者邮箱-昵称-插件名」的格式
const pluginKey = 'dumpywizard-editorconfig-plus'

const { position, inject, unregister } = context.injectComponent

class PluginManager extends Manager {

    private disposals: IDisposable[] = []

    private async handle(f: file.IFileNode, activeEditor: editor.IActiveEditor) {
        interface ConfigInfo { dir: file.IFileNode, config: { [key: string]: string } }
        const configInfos = async (): Promise<ConfigInfo[]> => {
            const res = []
            let dir = f.parent
            while (true) {
                const configFile = dir.children.find(v => !v.isDir && v.name === '.editorconfig')
                let isRoot = false
                if (configFile) {
                    const config = await parse(await file.getFileContent(configFile.path))
                    isRoot = 'true' === config.root
                    res.unshift({ dir, config })
                }
                if (isRoot || dir.isRoot)
                    break
                dir = dir.parent
            }
            return res
        }
        const merged = ((configInfos: ConfigInfo[]) => {
            const res = {}
            const option: minimatch.IOptions = { noext: true, dot: true, matchBase: true }
            configInfos.forEach(info => {
                Object.keys(info.config).forEach(key => {
                    if (key === 'root')
                        return
                    if (minimatch(f.path.substring(info.dir.path.length + 1), key, option)) {
                        Object.assign(res, info.config[key])
                    }
                })
            })
            return res
        })(await configInfos())
        console.log(merged)
        const applyToEditor = ((merged: { [key: string]: string }) => {
            const editor = activeEditor.editor

            const textModelOption: monaco.editor.ITextModelUpdateOptions = {}
            const tabSize = merged['tab_width'] || merged['indent_size']
            if (tabSize)
                textModelOption.tabSize = parseInt(tabSize)
            if (merged['indent_style'] === 'space')
                textModelOption.insertSpaces = true
            if (merged['indent_style'] === 'tab')
                textModelOption.insertSpaces = false
            if (merged['trim_trailing_whitespace'] === 'true')
                textModelOption.trimAutoWhitespace = true
            editor.getModel().updateOptions(textModelOption)

            if (merged['end_of_line']) {
                const eof = merged['end_of_line'].toLowerCase()
                const EOFLS = monaco.editor.EndOfLineSequence
                const eofseq = eof === 'lf' ? EOFLS.LF : eof === 'crlf' ? EOFLS.CRLF : null
                if (eofseq !== null)
                    editor.getModel().setEOL(eofseq)
                else
                    console.log(`The EOF: ${merged['end_of_line']} is not supported now`)
            }

            // todo: encoding

            if (merged['lang_ext']) {
                const ext = merged['lang_ext'].toLowerCase()
                monaco.editor.setModelLanguage(editor.getModel(), file.findLanguageByextension(ext).id)
            }

            if (merged['lang_id']) {
                const id = merged['lang_id']
                monaco.editor.setModelLanguage(editor.getModel(), id)
            }
        })(merged)
    }

    pluginWillMount() {
        this.disposals.push(editor.registerActiveEditorChangeHandler(args => {
            const activeEditor = editor.getActiveEditor()
            this.handle(file.getFileNode(args.uri.replace(/.*working-dir/, '')), activeEditor)
        }))
    }

    pluginWillUnmount() {
        // 卸载组件
        this.disposals.forEach(d => d())
    }
}

appRegistry([{
    Manager: PluginManager,
    key: pluginKey,
}])

